MACRO(CHANGE_EXTENSION output var new_ext)
    GET_FILENAME_COMPONENT(FileName ${var} NAME_WE)
    GET_FILENAME_COMPONENT(Path ${var} PATH)
    SET(${output} ${Path}/${FileName}.${new_ext})
ENDMACRO()

MACRO(SET_LAPACK_LINK_LIBRARIES name)

    IF( FASTFEM_USE_BLAS_LAPACK )
        IF( FASTFEM_USE_MKL AND MKL_FOUND )
            TARGET_LINK_LIBRARIES(${name} ${MKL} )
        ENDIF( FASTFEM_USE_MKL AND MKL_FOUND )

        IF( FASTFEM_USE_ACCELERATE_FRAMEWORK )
            TARGET_LINK_LIBRARIES(${name} ${ACCELERATE_FRAMEWORK_LINK_FLAGS})
        ENDIF ( FASTFEM_USE_ACCELERATE_FRAMEWORK )

        IF( FASTFEM_USE_SYSTEM_BLAS_LAPACK )
            TARGET_LINK_LIBRARIES(${name} ${NATIVE_LAPACK} ${NATIVE_BLAS})
        ENDIF( FASTFEM_USE_SYSTEM_BLAS_LAPACK )

    ENDIF( FASTFEM_USE_BLAS_LAPACK )

    IF( FASTFEM_USE_METIS )
        TARGET_LINK_LIBRARIES(${name} optimized ${METIS_LIB} debug
            ${METIS_LIB} )
    ENDIF( FASTFEM_USE_METIS )

ENDMACRO(SET_LAPACK_LINK_LIBRARIES name)

MACRO(SET_COMMON_PROPERTIES name)
	SET_TARGET_PROPERTIES(${name} PROPERTIES VERSION ${FASTFEM_VERSION})

    SET_TARGET_PROPERTIES(${name} PROPERTIES DEBUG_POSTFIX -g)
    SET_TARGET_PROPERTIES(${name} PROPERTIES MINSIZEREL_POSTFIX -ms)
    SET_TARGET_PROPERTIES(${name} PROPERTIES RELWITHDEBINFO_POSTFIX -rg)

    IF (NOT ${CMAKE_CXX_FLAGS} MATCHES "-pipe")
    	#STRING (REPLACE " -pipe" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
    	SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe")
    ENDIF (NOT ${CMAKE_CXX_FLAGS} MATCHES "-pipe")

    IF( OPENMP_FOUND )
    	IF (NOT ${CMAKE_CXX_FLAGS} MATCHES "${OpenMP_CXX_FLAGS}")
    		#STRING (REPLACE " ${OpenMP_CXX_FLAGS}" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
    		SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
    		#SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
    		SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_CXX_FLAGS}")
    	ENDIF (NOT ${CMAKE_CXX_FLAGS} MATCHES "${OpenMP_CXX_FLAGS}")
    ENDIF( OPENMP_FOUND )

    IF( ${CMAKE_COMPILER_IS_GNUCXX} )
	    IF(FASTFEM_ENABLE_PROFILE)
	        SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
	        SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg")
	        SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pg")
            SET(LINK_FLAGS "${LINK_FLAGS} -pg")
        ENDIF(FASTFEM_ENABLE_PROFILE)
    ENDIF( ${CMAKE_COMPILER_IS_GNUCXX} )

    # Prevent including these common flags multiple times.
    IF (NOT ${CMAKE_CXX_FLAGS_DEBUG} MATCHES ".*DFASTFEM_DEBUG.*")
        SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DFASTFEM_DEBUG")

        IF( NOT MSVC )
            IF (NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
                SET(CMAKE_CXX_FLAGS_DEBUG
                    "${CMAKE_CXX_FLAGS_DEBUG} -fpermissive -Wno-deprecated")
            ELSE ()
                SET(CMAKE_CXX_FLAGS_DEBUG
                    "${CMAKE_CXX_FLAGS_DEBUG} -Wno-deprecated")
            ENDIF()

            SET(CMAKE_CXX_FLAGS_RELEASE
                    "${CMAKE_CXX_FLAGS_RELEASE} -Wno-deprecated")
        ENDIF( NOT MSVC)

        IF( ${CMAKE_COMPILER_IS_GNUCXX} )
          IF (NOT ${CMAKE_CXX_FLAGS_RELEASE} MATCHES "-O3")
            SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
          ENDIF (NOT ${CMAKE_CXX_FLAGS_RELEASE} MATCHES "-O3")
          IF (APPLE)
            SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -static-libgcc")
          ELSE (APPLE)
            SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -static")
          ENDIF (APPLE)
        	SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -msse4.2 -march=corei7 -funroll-loops -ffast-math -ftree-vectorize -fexpensive-optimizations")
        ELSE ()
        	STRING (REPLACE "-O3" "" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
        	#STRING (REPLACE "-O2" "" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
        	SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2 -unroll-aggressive -no-prec-div -ip -parallel -axSSE4.2 -vec-report1")
        	SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -parallel -axSSE4.2")
        ENDIF( ${CMAKE_COMPILER_IS_GNUCXX} )

        SET(CMAKE_CXX_FLAGS_RELEASE
                    "${CMAKE_CXX_FLAGS_RELEASE} -DFASTFEM_RELEASE")
    ENDIF(NOT ${CMAKE_CXX_FLAGS_DEBUG} MATCHES ".*DFASTFEM_DEBUG.*")

    IF( CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" )
        # The static libraries must be compiled with position independent
        # code on 64 bit Linux.
        SET_PROPERTY(TARGET ${name} APPEND PROPERTY COMPILE_FLAGS "-fPIC")
    ENDIF( CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" )
ENDMACRO(SET_COMMON_PROPERTIES name)


MACRO(ADD_FASTFEM_EXECUTABLE name component sources)
    IF( ${ARGC} LESS 4 )
        ADD_EXECUTABLE(${name} ${${sources}})
    ELSE( ${ARGC} LESS 4 )
        ADD_EXECUTABLE(${name} ${${sources}} ${${ARGV3}})
    ENDIF( ${ARGC} LESS 4)

    SET_COMMON_PROPERTIES(${name})

    IF( FASTFEM_USE_MKL AND MKL_FOUND )
        TARGET_LINK_LIBRARIES(${name} ${MKL} )
        SET_TARGET_PROPERTIES(${name}
                PROPERTIES COMPILE_FLAGS "${THE_COMPILE_FLAGS} -DMKL_ILP64")
    ENDIF( FASTFEM_USE_MKL AND MKL_FOUND )


    TARGET_LINK_LIBRARIES(${name}
        optimized polylib debug polylib
        optimized fastfem debug fastfem
        ${Boost_THREAD_LIBRARY}
        ${Boost_IOSTREAMS_LIBRARY}
        ${Boost_DATE_TIME_LIBRARY}
        ${Boost_FILESYSTEM_LIBRARY}
        ${Boost_PROGRAM_OPTIONS_LIBRARY}
        ${Boost_SYSTEM_LIBRARY}
	)
    ADD_DEPENDENCIES(${name} boost)

    IF( ${CMAKE_SYSTEM} MATCHES "Linux.*" )
		TARGET_LINK_LIBRARIES(${name} optimized rt debug rt)

        # The boost thread library needs pthread on linux.
        GET_TARGET_PROPERTY(THE_COMPILE_FLAGS ${name} COMPILE_FLAGS)
        GET_TARGET_PROPERTY(THE_LINK_FLAGS ${name} LINK_FLAGS)

        # It is possible these flags have not been set yet.
        IF(NOT THE_COMPILE_FLAGS)
            SET(THE_COMPILE_FLAGS "")
        ENDIF(NOT THE_COMPILE_FLAGS)

        IF(NOT THE_LINK_FLAGS )
	        SET(THE_LINK_FLAGS "")
        ENDIF(NOT THE_LINK_FLAGS)

        SET_TARGET_PROPERTIES(${name}
                PROPERTIES COMPILE_FLAGS "${THE_COMPILE_FLAGS} -pthread")
        SET_TARGET_PROPERTIES(${name}
                PROPERTIES LINK_FLAGS "${THE_LINK_FLAGS} -pthread")

    ENDIF( ${CMAKE_SYSTEM} MATCHES "Linux.*" )

    IF( ${CMAKE_SYSTEM} MATCHES "Darwin-*")
        SET_TARGET_PROPERTIES(${name}
            PROPERTIES LINK_FLAGS "-Wl,-undefined,dynamic_lookup -Wl,-rpath,${CMAKE_INSTALL_PREFIX}/${LIB_DIR} -Wl,-rpath,${Boost_LIBRARY_DIRS}")
    ENDIF( ${CMAKE_SYSTEM} MATCHES "Darwin-*")

    SET_PROPERTY(TARGET ${name} PROPERTY FOLDER ${component})
	INSTALL(TARGETS ${name}
		RUNTIME DESTINATION ${FASTFEM_BIN_DIR} COMPONENT ${component} OPTIONAL
		ARCHIVE DESTINATION ${FASTFEM_LIB_DIR} COMPONENT ${component} OPTIONAL
		LIBRARY DESTINATION ${FASTFEM_LIB_DIR} COMPONENT ${component} OPTIONAL)

ENDMACRO(ADD_FASTFEM_EXECUTABLE name component sources)

MACRO(ADD_FASTFEM_LIBRARY name component type)
    ADD_LIBRARY(${name} ${type} ${ARGN})

    # NIST Sparse BLAS only static, so link into Nektar libraries directly.
    ADD_DEPENDENCIES(${name} boost polylib)
    SET_PROPERTY(TARGET ${name} PROPERTY FOLDER ${component})

    SET_COMMON_PROPERTIES(${name})

    # Set properties for building shared libraries
    IF( ${type} STREQUAL "SHARED" )
        # Properties specific to Mac OSX
        IF( ${CMAKE_SYSTEM} MATCHES "Darwin-*")
            # We allow undefined symbols to be looked up dynamically at runtime
            # from the boost libraries linked by the executables.
            SET_TARGET_PROPERTIES(${name}
                PROPERTIES LINK_FLAGS "-Wl,-undefined,dynamic_lookup")
        ENDIF( ${CMAKE_SYSTEM} MATCHES "Darwin-*")
    ENDIF( ${type} STREQUAL "SHARED" )

    INSTALL(TARGETS ${name}
        EXPORT FastFEMLibraries
		RUNTIME DESTINATION ${FASTFEM_BIN_DIR} COMPONENT ${component} OPTIONAL
		ARCHIVE DESTINATION ${FASTFEM_LIB_DIR} COMPONENT ${component} OPTIONAL
		LIBRARY DESTINATION ${FASTFEM_LIB_DIR} COMPONENT ${component} OPTIONAL)

ENDMACRO(ADD_FASTFEM_LIBRARY name component type)

MACRO(ADD_FASTFEM_DEMO name component source)

    ADD_EXECUTABLE(${name} ${source} ${ARGN})

    SET_COMMON_PROPERTIES(${name})

    # TODO - If your executable needs to link to any other libraries,
    # add them here.
    TARGET_LINK_LIBRARIES(${name}
            optimized fastfem debug fastfem
            optimized polylib debug polylib
	    ${Boost_THREAD_LIBRARY}
            ${Boost_IOSTREAMS_LIBRARY}
	    ${Boost_ZLIB_LIBRARY}
            ${Boost_DATE_TIME_LIBRARY}
            ${Boost_PROGRAM_OPTIONS_LIBRARY}
            ${Boost_SYSTEM_LIBRARY}
    )

    IF( ${CMAKE_SYSTEM} MATCHES "Linux.*")
        TARGET_LINK_LIBRARIES(${name} optimized rt debug rt)
    ENDIF()

    IF( ${CMAKE_SYSTEM} MATCHES "Darwin-*")
        SET_TARGET_PROPERTIES(${name}
            PROPERTIES LINK_FLAGS "-Wl,-undefined,dynamic_lookup -Wl,-rpath,${CMAKE_INSTALL_PREFIX}/${LIB_DIR} -Wl,-rpath,${Boost_LIBRARY_DIRS}")
    ENDIF( ${CMAKE_SYSTEM} MATCHES "Darwin-*")
	SET_PROPERTY(TARGET ${name} PROPERTY FOLDER ${component})
    INSTALL(TARGETS ${name}
		RUNTIME DESTINATION ${FASTFEM_BIN_DIR} COMPONENT ${component})

ENDMACRO(ADD_FASTFEM_DEMO name component source)

# Adds a test with a given name.
# The Test Definition File should be in a subdirectory called Tests relative
# to the CMakeLists.txt file calling this macros. The test file should be called
# NAME.tst, where NAME is given as a parameter to this macro.
MACRO(ADD_FASTFEM_TEST name)
    GET_FILENAME_COMPONENT(dir ${CMAKE_CURRENT_SOURCE_DIR} NAME)
    ADD_TEST(NAME ${dir}_${name}
         COMMAND Tester ${CMAKE_CURRENT_SOURCE_DIR}/tests/${name}.tst)
ENDMACRO(ADD_FASTFEM_TEST)
